
#include <mysqld_error.h>
#include "dbaccess.h"

#include <stdio.h>

using namespace std;

CDataAccess::CDataAccess()
{
    m_mysqlSock = NULL;
    m_bConnected = false;
}

CDataAccess::CDataAccess(MYSQL *sock)
{
    m_mysqlSock = sock;
    m_bConnected = true;
}

CDataAccess::~CDataAccess()
{
    DisConnect();
}

int CDataAccess::Connect(const string &sHost, const string &sUser, const string &sPwd, const string &sDatabase)
{
    if (m_bConnected)
    {
        return 0;
    }

    m_mysqlSock = mysql_init(NULL);

    if(!::mysql_real_connect(m_mysqlSock, sHost.c_str(), sUser.c_str(), sPwd.c_str(),
                                    sDatabase.c_str(), 3306, NULL, 0))
    {
        return -1;
    }
    m_bConnected = true;

    return 0;
}

int CDataAccess::DisConnect()
{
    if (m_bConnected == false)
    {
        return 0;
    }

    if (m_mysqlSock == NULL)
    {
        return 0;
    }

    mysql_close(m_mysqlSock);
    m_mysqlSock = NULL;
    m_bConnected = false;
    return 0;
}

int CDataAccess::SwitchDB(const string& sDBName)
{
    if (m_bConnected != true)
    {
        return -1;
    }
    if (::mysql_select_db(m_mysqlSock, sDBName.c_str()) != 0)
    {
        return -1;
    }

    return 0;
}

MYSQL* CDataAccess::GetConnentHandle()
{
    return m_mysqlSock;
}

const char* CDataAccess::GetLastErrorString()
{
    return mysql_error(m_mysqlSock);
}

int CDataAccess::GetLastErrno()
{
    return (int)mysql_errno(m_mysqlSock);
}

int CDataAccess::Command(const string &sSql)
{
    m_sSql = sSql;
    return 0;
}

int CDataAccess::AddParameters(const string &sPara, const string &sValue)
{
    size_t iLoc = m_sSql.find(sPara, 0);
    if (iLoc != string::npos)
    {
        char *pValue = new char[sValue.length() * 2 + 1];
        mysql_real_escape_string(m_mysqlSock, pValue, sValue.c_str(), sValue.length());
        m_sSql.replace(iLoc, sPara.length(), pValue);
        delete[] pValue;
    }
    return 0;
}

int CDataAccess::AddParameters(const string &sPara, int iValue)
{
    char tmp[16] = {0};
    snprintf(tmp, 16, "%d", iValue);
    const string sValue = tmp;
    return AddParameters(sPara, sValue);
}

int CDataAccess::AddParameters(const string &sPara, char cValue)
{
    char tmp[2] = {cValue, 0x00};
    const string sValue = tmp;
    return AddParameters(sPara, sValue);
}

int CDataAccess::AddParameters(const string &sPara, unsigned int uiValue)
{
    char tmp[16] = {0};
    snprintf(tmp, 16, "%u", uiValue);
    const string sValue = tmp;
    return AddParameters(sPara, sValue);
}


int CDataAccess::AddParameters(const string &sPara, unsigned long uiValue)
{
    char tmp[16] = {0};
    snprintf(tmp, 16, "%lu", uiValue);
    const string sValue = tmp;
    return AddParameters(sPara, sValue);
}

int CDataAccess::Execute()
{
    if (mysql_real_query(m_mysqlSock, m_sSql.c_str(), m_sSql.length()) != 0)
    {
        if( ER_NO_SUCH_TABLE == mysql_errno(m_mysqlSock) )
        {
            return -2;
        }
        return -1;
    }

    my_ulonglong affected = GetAffectedRowsCount();
    if (affected == 0)
    {
        return 0;
    }
    
    return 0;
}

int CDataAccess::Execute(CDataTable &table)
{
    if (mysql_real_query(m_mysqlSock, m_sSql.c_str(), m_sSql.length()) != 0)
    {
        if( ER_NO_SUCH_TABLE == mysql_errno(m_mysqlSock) )
        {
            return -2;
        }
        return -1;
    }

    MYSQL_RES* res = NULL;
    if ((res = mysql_store_result(m_mysqlSock)) == NULL)
    {
        return -1;
    }

    MYSQL_FIELD *fields = NULL;
    unsigned int num_fields = mysql_num_fields(res);
    unsigned int i = 0;
    fields = mysql_fetch_fields(res);

    MYSQL_ROW row = NULL;
    while ((row = mysql_fetch_row(res)))
    {
        map <string, string> mFields;
        for(i = 0; i < num_fields; ++i)
        {
            mFields.insert(make_pair(fields[i].name, row[i] ? row[i] : ""));
        }
        table.Row.push_back(mFields);
    }

    mysql_free_result(res);

    return 0;
}

